#ifndef BLOCKQUEUE_H
#define BLOCKQUEUE_H

#include <QObject>

#include <thread>
#include <mutex>
#include <queue>
#include <atomic>

template<typename T>
class BlockQueue
{
public:
    /**
     * @brief  BlockQueue 构造函数
     * @return
     */
    BlockQueue() { m_abort = false; }

    /**
     * @brief  ~BlockQueue 析构函数
     * @return
     */
    ~BlockQueue() {}

public:
    /**
     * @brief  push 添加数据
     * @param  data
     * @return void
     */
    void push(const T &data)
    {
        // 加锁
        std::unique_lock<std::mutex> lock(m_mutex);
        m_queue.push(data);
        m_cv.notify_all();
    }

    /**
     * @brief  pop 获取数据
     * @return T
     */
    bool pop(T &data)
    {
        // 加锁
        std::unique_lock<std::mutex> lock(m_mutex);
        while (!m_abort && m_queue.empty())
        {
            m_cv.wait(lock);
        }

        if (m_queue.empty())
        {
            return false;
        }

        data = m_queue.front();
        m_queue.pop();
        return true;
    }

    /**
     * @brief  empty 队列是否为空
     * @return bool
     */
    bool empty()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_queue.empty();
    }

    /**
     * @brief  size 队列大小
     * @return size_t
     */
    size_t size()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_queue.size();
    }

    /**
     * @brief  clear 清空队列
     * @return void
     */
    void  clear()
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        std::queue<T> empty;
        swap(empty, m_queue);
    }

    /**
     * @brief  abort 中止阻塞
     * @return void
     */
    void abort()
    {
        m_abort = true;
        std::unique_lock<std::mutex> lock(m_mutex);
        m_cv.notify_all();
    }

private:
    /** 队列
     */
    std::queue<T> m_queue;

    /** 锁
     */
    std::mutex m_mutex;

    /** 条件变量
     */
    std::condition_variable m_cv;

    /** 中止阻塞
     */
    std::atomic<bool> m_abort;
};

#endif // BLOCKQUEUE_H
